spaceharderfandomcom-20200214-history
Tutorial 3: Creating a Unit
This tutorial will guide you through the creation of a simple unit that will appear in SpaceRTS, including making the XML file, importing the XML file into the game, and making the unit able to be spawned by scripts, selected by the player to go on missions, and built by other units. Design and Art Let's start by deciding what kind of unit to make. In this tutorial, we're going to make a "support ship." It's going to be a medium-sized ship with a dinky little gun for self-defense, and a repair turret to support other units. In order to make the unit, we'll need the following assets: *A sprite for the hull of the ship, on top of which other sprites will be drawn. *A sprite for the team-color of the ship. *A sprite for the gun, and a team-color sprite for that gun. *A sprite for the repair turret, and a team-color sprite for it. *Sprites for the thrusters of the ship. *Particle effects for the ship's repair turret. *Particle effects for the ship's explosion. *Sounds for shooting, repairing, exploding, etc. Making all of these assets can be a daunting task, and that's why I'm going to re-use a lot of assets from other units in the game to make this one (and so should you when making your own units!). Let's start by making the hull of the ship. All sprites should be facing to the right, and should be perfectly oriented horizontally. This is because the SpaceRTS engine assumes that all sprites have a "forward" direction to the right, and a "left" direction which is up, it then rotates the sprites counter-clockwise. This is called a "right handed coordinate system." Here's a hull sprite I made for the ship that's a modification of the existing frigate hull (found in Content/Ships/Enforcers/enforcer_frigate.png) Basically, it's just a frigate that looks like a medic. Easy and readable. I then saved this sprite to SpaceRTSContent/Ships/Enforcers/enforcer_support.png. Now, here's a sprite for the teamcolor. It's just an exact copy of the Content/Ships/Enforcers/enforcer_frigate_teamcolor.png sprite. SpaceRTS colors units to their team by drawing a second sprite on top of the unit, and tinting that sprite the color of the unit's team. Therefore, all team-color sprites should be shades of grey. Now, we'll need sprites for the guns. For this one, I'll just use the machine gun sprite in Content/Guns/frigategun3.png, and it's team color sprite. We'll also need sprites for the muzzle flashes and thrusters. I'll also be re-using sprites from the repository. Content/bigthruster2.png for the thrusters, and Content/muzzleflash1.png for the muzzle flash. For the particle effects, we'll use Content/repairTractor.xml for the ship's repair beam, Content/bigexplosion.xml for the explosion upon death, and Content/pop.xml for the explosions of the ships' bullets. For sounds, we'll use Content/engineloop.wav for the low hum the player will hear when looking at the support frigate, Content/explosion1.wav for the explosion when the support frigate dies, Content/pew.wav for the sound the repair tractor makes, and Content/machinegun.wav for the sound the support frigate's gun makes. To import all of the required content into the game, just open up visual studio, and drag all of the files into the SpaceRTSContent project. Creating the XML File Outer Layer Open up your favorite XML editor and create a new file called EnforcerSupport.xml. Copy the following lines into the file: enforcer_support_frigate true true false false 0 0 0 1.917476 Cirlce 0.78125 0.78125 These lines constitute the outer layer of a unit. They define the base component of the unit, which you can see here is "PhysBody". This means that the unit is itself a physically simulated object in the world. All other components will be children of the PhysBody, and so will move around when the Physics engine tells them to. Most objects in the SpaceRTS game engine are PhysBodies. Child Components Now, in the "childList" field, we're going to add the child components of the ship. We'll start with the ship's sprite. Add the following inside the "childList" field: Sprite baseSprite false false 0 0 0 Ships/Enforcers/enforcer_support 255 255 255 255 None 0 0 1 1 0 false This will make the ship have a child component, the enforcer_support sprite we made earlier, as its one and only child, at the origin of the object. Notice that for the textureAsset, you have to use the full XNA asset path. The rest of the fields are pretty self-explanatory. They are mostly interited from KComponent, with additional fields for effects applied to the sprite, like scaling and tinting. Now, let's add the team color sprite just below the Sprite component Team Color teamColor false false 0 0 0 Ships/Enforcers/enforcer_support_teamcolor 255 255 255 255 None 0 0 1 1 0 true This component is identical to the previous component, except that it has "tintWithTeamColor" set to true, and has a different textureAsset field. Now, if we spawned the unit, it would just be a passive object that moved around with physics, and which had stripes tinted to its team color. So to make it move around, let's add an AI component to it. AI AI false false 0 0 0 <_mass>1.917476 <_radius>0.390625 <_speed>0 <_maxForce>3 <_maxSpeed>4 0 0 5 25 0.8 This component wraps the OpenSteerDotNet Vehicle class. OpenSteerDotNet is an external library that handles flocking behaviors for XNA. The only thing this class will do is accept orders from the player to move to a location, and will allow the unit to dog fight with other units. The important fields here are mostly found in "steering," which is the OpenSteerDotNet vehicle itself. Make sure that the mass and radius given here are the same as the mass and radius of the physics object. The max force and speed define how quickly the ship can accelerate and move. The brake radius defines a region in which the ship will consider itself to be "arrived" at a target. The sense radius defines the region in which the unit will automatically sense enemies. The brake strength defines how quickly the unit can decellerate to a stop once it has started moving. Now, let's add the thrusters to the back of the ship. Thrusters ThrusterA false false -1.2 -0.171875 0 bigthruster2 255 255 255 255 None 0 0 2 2 0 ThrusterB false false -1.2 0.171875 0 bigthruster2 255 255 255 255 None 0 0 2 2 0 Thrusters are merely graphical effects which extend Sprite, and grow with the velocity of the unit. The only really important thing to note here is that the relative positions of the thrusters have changed here, and that the two thrusters are opposite to each other. Let's go ahead and add the machine gun that the unit will use to defend itself now. Turret machineGun false false turretTeamcolor false false 0 0 0 Guns/frigategun3_teamcolor 255 255 255 255 None 0 0 1 1 0 true muzzleFlash false false 0.01 0 0 muzzleflash1 255 255 255 255 None 0 0 1 1 0 0.15 Seconds -1.0 0 3.14159 Guns/frigategun3 255 255 255 255 None 0 0 1 1 0 0 6 0.1 1 sundaybullets pop lowhit 1 1 false 0 0.05 Seconds 0.5 Seconds 6 15 35 0.1 machinegun true This is a very complicated component. The first thing you should know is that the turret itself extends Sprite, so it has all the fields of Sprite. Second, the turret has two child components: its team color sprite, and its muzzle flash. The team color sprite is drawn on top of the turret, and the muzzle flash is drawn when the turret sends a message to it upon firing on an enemy. Besides the child components, the turret also contains a definition for the kind of bullet it will fire. This is located in "bulletDefinition." That contains several useful things like the amount of damage the bullet does, what texture to draw, what sounds to make, etc. The rest of the fields are somewhat self-explanatory. If you have any questions please ask. Now, let's add the repair tractor beam to the unit so that it can heal other units. Repair Tractor repairer false false 0.0 0.0 0 10 0.01 repairTractor pew This component will allow the unit to repair other units within a range of 10, at a rate of 0.01 hit points per second. If you want, you can add a sprite as a child to the repair tractor so that it actually has a physical manifestation. Now, the unit is pretty much done. What's left is some book-keeping for the unit's health, and effects that occur on the unit's death. Health false false 0 0 0 30 0 30 0 This is a very simple component defining the health of the unit. Units can have health and shield values. If the unit has any shields, they act as temporary hit points which are depleted (and repaired) before the hit points of the unit are depleted. Death Effects deathExplosion false false 0 0 0 bigexplosion explosion1 Death This component spawns a big particle effect and makes an explosion sound when the unit dies. Icon frigateIcon false false 0 0 0 triangle true false This component draws a little arrow over the unit when the player has zoomed out. If you were to select "drawHintOffscreen," then when the unit was not visible by the screen, an arrow would be drawn in its direction. This is useful for big, important units critical to the story to make it easier for the player to find things. And that's it. This is all that's needed for the unit to be functional in the game. Importing the XML File To import the unit that you just created into the game, do the following: #Open the SpaceRTS solution. #Navigate to the SpaceRTSContent project. #Drag the XML file you just created over the SpaceRTSContent project. This will import the unit as an asset. #Right click on the XML file that just appeared on the sidebar of the SpaceRTSConent project. Select "Properties." #This will show a properties bar. In the properties bar, change Content Importer to "Component Importer", and Content Processor to "SpaceRTSPipeline.ComponentProcessor". Now, the unit will be a loadable asset in the game. Spawning the Unit With a Script Now that the unit is usable as an asset, we can spawn it in a level using a script. To do this most easily, we can use a SpawnRegion script. Open up Content/Levels/Level2.xml (this is a test level used for debugging things) and look for the lines: enforcerfrigate enforcerfighter sunday 2 2 1 This lists a number of entities to spawn in a region of the map. In the level, these specific lines mean that 2 frigates, 2 fighters, and 1 sunday will be spawned in the region. So, change these lines to this: enforcerfrigate enforcerfighter enforcersupport sunday 2 2 1 1 Save the level, and run the game. The new unit will appear in the level! Making the Unit Usable To make the unit usable in the game, we have to add it to the list of units that the player can select to take on a mission, and (if we want) to a list of units buildable by carriers. To make the unit usable, again go to Level2.xml and locate the lines: enforcerscout enforcerfighter enforcerbomber enforcerfrigate enforcercarrier enforcerharvester 1 10 20 30 50 30 These define, for that specific level, which units can be selected by the player. The "shipWeights" field defines how much each ship costs. Add lines to make it look like this: enforcerscout enforcerfighter enforcerbomber enforcerfrigate enforcercarrier enforcerharvester enforcersupport 1 10 20 30 50 30 40 This adds the support frigate to the list of available ships, and makes it cost 40 points. Now, we have to register the unit with a build icon to make it usable by the game engine. In SpaceRTS.cs, you should see the following lines: GameGUI.RegisterIcon("ducky", "duckyicon"); GameGUI.RegisterIcon("hiveguy", "hiveguyicon"); GameGUI.RegisterIcon("harvester", "harvestericon"); GameGUI.RegisterIcon("scout", "scouticon"); GameGUI.RegisterIcon("enforcerscout", "enforcer_scout_icon"); GameGUI.RegisterIcon("enforcerfrigate", "enforcer_frigate_icon"); GameGUI.RegisterIcon("enforcerfighter", "enforcer_fighter_icon"); GameGUI.RegisterIcon("enforcerharvester", "enforcer_harvester_icon"); GameGUI.RegisterIcon("enforcercarrier", "enforcer_carrier_icon") GameGUI.RegisterIcon("enforcerbomber", "enforcer_fighter_icon"); This registers certain icons with their associated ships. This is needed for the game engine to know which image to display for the player to select or build a ship. Add the following line to this list: GameGUI.RegisterIcon("enforcersupport", "enforcer_frigate_icon"); Now, the unit will be selectable by the player.